package com.ruoyi.common.core.allocator;

import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

import java.util.UUID;

public class RedisIdAllocator {
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;
    private static final String DATA_CENTER_ID_KEY = "snowflake:data_center_id";
    private static final String WORKER_ID_PREFIX = "snowflake:worker_id:";
    private static final long MAX_DATA_CENTER_ID = 31; // 5 位数据中心 ID，最大值为 2^5 - 1
    private static final long MAX_WORKER_ID = 31; // 5 位工作机器 ID，最大值为 2^5 - 1
    private static final long LOCK_EXPIRE_TIME = 10000; // 锁的过期时间，单位：毫秒

    private final Jedis jedis;

    public RedisIdAllocator() {
        this.jedis = new Jedis(REDIS_HOST, REDIS_PORT);
    }

    /**
     * 分配数据中心 ID
     * @return 数据中心 ID
     */
    public long allocateDataCenterId() {
        long dataCenterId = jedis.incr(DATA_CENTER_ID_KEY) % (MAX_DATA_CENTER_ID + 1);
        return dataCenterId;
    }

    /**
     * 分配工作机器 ID
     * @param dataCenterId 数据中心 ID
     * @return 工作机器 ID
     */
    public long allocateWorkerId(long dataCenterId) {
        String workerIdKey = WORKER_ID_PREFIX + dataCenterId;
        String lockKey = workerIdKey + ":lock";
        String lockValue = UUID.randomUUID().toString();

        // 获取分布式锁
        SetParams setParams = new SetParams();
        setParams.nx().px(LOCK_EXPIRE_TIME);
        String result = jedis.set(lockKey, lockValue, setParams);
        if ("OK".equals(result)) {
            try {
                long workerId = jedis.incr(workerIdKey) % (MAX_WORKER_ID + 1);
                return workerId;
            } finally {
                // 释放分布式锁
                if (lockValue.equals(jedis.get(lockKey))) {
                    jedis.del(lockKey);
                }
            }
        } else {
            throw new RuntimeException("Failed to acquire lock for worker ID allocation");
        }
    }

    /**
     * 释放工作机器 ID
     * @param dataCenterId 数据中心 ID
     * @param workerId 工作机器 ID
     */
    public void releaseWorkerId(long dataCenterId, long workerId) {
        String workerIdKey = WORKER_ID_PREFIX + dataCenterId;
        String lockKey = workerIdKey + ":lock";
        String lockValue = UUID.randomUUID().toString();

        // 获取分布式锁
        SetParams setParams = new SetParams();
        setParams.nx().px(LOCK_EXPIRE_TIME);
        String result = jedis.set(lockKey, lockValue, setParams);
        if ("OK".equals(result)) {
            try {
                // 这里可以实现更复杂的释放逻辑，如记录已释放的 ID 等
                // 简单示例：不做其他操作
            } finally {
                // 释放分布式锁
                if (lockValue.equals(jedis.get(lockKey))) {
                    jedis.del(lockKey);
                }
            }
        } else {
            throw new RuntimeException("Failed to acquire lock for worker ID release");
        }
    }
}
